package com.yuma.rabbitmq.reliability1productor.config;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;


@Slf4j
@Configuration
public class MQProducerAckConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @PostConstruct   // 调用完rabbitTemplate对象的构造方法后就调用此方法，把配置设置给rabbitTemplate对象
    public void initRabbitTemplate(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    // 消息是否成功到达了队列，如果到达队列不执行此回调，没到达队列就执行此回调
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.info("returnedMessage() 回调函数 消息主体: " + new String(returnedMessage.getMessage().getBody()));
        log.info("returnedMessage() 回调函数 应答码: " + returnedMessage.getReplyCode());
        log.info("returnedMessage() 回调函数 描述: " + returnedMessage.getReplyText());
        log.info("returnedMessage() 回调函数 消息使用的交换器 exchange: " + returnedMessage.getExchange());
        log.info("returnedMessage() 回调函数 消息使用的路由键 routing: " + returnedMessage.getRoutingKey());
    }

    // RabbitTemplate.ConfirmCallback 是否到达了交换机的回调方法
    @Override   // CorrelationData保证了数据的唯一性的信息, rabbit返回到达结果ack为true到达了交换机,ack为false则第三个参数couse就是失败原因
    public void confirm(CorrelationData correlationData, boolean ack, String couse) {
        System.out.println("RabbitMQ 交换机  correlationData:" + correlationData);
        if (ack) {
            log.info("消息到达交换机");
        } else {
            log.info("消息未到达交换机,原因:" + couse);
            // 失败没到达交换机可以人为解决，如果是因为RabbitMQ服务器宕机可以重新发送
            // correlationData重新发送
            // correlationData.getId();  // 保证了消息唯一的id
            // correlationData.setReturned(); // 设置应该返回的预期值
        }
    }
}
